/*
 *    FPNode.java
 *    Copyright (C) 2011 University of Waikato, Hamilton, New Zealand
 *    @author Maciek Jarka (www.admire-project.eu)
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package moa.associations;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import weka.associations.Item;

/** Node of frequent pattern tree. Store content of time window
 * 
 * @author maciek
 *
 */
public class FPNode {

    Item item;

    int support;

    List<FPNode> children;

    FPNode nextHeader, parent;

    int tidsum = 0;

    static FPTreeHeaders headers = new FPTreeHeaders();

    static HashMap<Integer, FPNode> tidmap = new HashMap<Integer, FPNode>();

    List<Integer> tidlist;

    public FPNode(Item item, FPNode parent) {
        support = 0;
        children = new ArrayList<FPNode>();
        this.item = item;
        this.parent = parent;
        tidlist = new ArrayList<Integer>();
    }

    public int calculateSupport(List<Item> mItems) {
        List<Item> items = new ArrayList<Item>();
        items.addAll(mItems);
        if (items.size() == 0) {
            return -1;
        }
        if (items.get(0).equals(this.item) && items.size() == 1) {
            return this.support;
        }
        if (items.get(0).equals(this.item)) {
            items.remove(0);
        }
        int totalSup = 0;

        for (FPNode node : this.children) {
            int cSup = -1;
            cSup = node.calculateSupport(items);
            if (cSup != -1) {
                totalSup += cSup;
            }
        }
        return totalSup;
    }

    public int calculateTidSum(List<Item> mItems) {
        List<Item> items = new ArrayList<Item>();
        items.addAll(mItems);
        if (items.size() == 0) {
            return -1;
        }
        if (items.get(0).equals(this.item) && items.size() == 1) {
            return this.tidsum;
        }
        if (items.get(0).equals(this.item)) {
            items.remove(0);
        }
        int sum = 0;

        for (FPNode node : this.children) {
            int tSum = -1;
            tSum = node.calculateTidSum(items);
            if (tSum != -1) {
                sum += tSum;
            }
        }
        return sum;
    }

    public void add(int tid, List<Item> items) {

        if (items.size() != 0) {
            if (items.get(0).equals(this.item)) {
                items.remove(0);
                support++;
                tidsum += tid;
                tidlist.add(tid);
            }
            if (items.size() == 0) {
                tidmap.put(Integer.valueOf(tid), this);
                return;

            }
            boolean found = false;
            for (FPNode n : children) {
                if (n.item.equals(items.get(0))) {
                    n.add(tid, items);
                    found = true;
                    break;
                }
            }
            if (!found) {
                FPNode newNode = new FPNode(items.get(0), this);
                headers.add(newNode);
                children.add(newNode);
                newNode.add(tid, items);
            }
        } else {
            return;
        }
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof FPNode) {
            return ((FPNode) o).item.equals(this.item);
        }
        return false;
    }

    public String toString() {
        return this.item.getAttribute().toString();
    }
}
